﻿"use strict";
document.body.classList.add("javascript");
const gcInput = document.getElementById('i-wc');
const glenInput = document.getElementById('i-wl');
const genb = document.getElementById('i-b');
const po = document.getElementById('clist');
var Project;
(function (Project) {
    function resetPrototype(o) {
        Object.setPrototypeOf(Object.getPrototypeOf(o) ?? o, null);
    }
    let Private;
    (function (Private) {
        Private.NODE_LINKS = Symbol("Project.NodeLink@links");
        Private.NODE_LETTER = Symbol("Project.NodeLink@letter");
        Private.LINK_PRIVATE = Symbol("Project.NodeLink@data");
    })(Private || (Private = {}));
    class Node {
        constructor(l, t = "other") {
            resetPrototype(this);
            this[Private.NODE_LINKS] = [];
            this.letter = l;
            this.type = t;
            Object.defineProperty(this, "length", {
                configurable: false,
                enumerable: true,
                get: () => {
                    return this[Private.NODE_LINKS].length;
                }
            });
        }
        [Private.NODE_LINKS];
        [Private.NODE_LETTER];
        get letter() {
            return this[Private.NODE_LETTER];
        }
        set letter(v) {
            this[Private.NODE_LETTER] = v;
        }
        type;
        at(i) {
            return this[Private.NODE_LINKS][i];
        }
        link(n, w) {
            return new NodeLink(this, n, w);
        }
        unlink(n) {
            n.remove();
        }
        doubleLink(n, w) {
            return [new NodeLink(this, n, w), new NodeLink(n, this, w)];
        }
        nodeLink(n) {
            for (let i = 0; i < this[Private.NODE_LINKS].length; i++) {
                const e = this[Private.NODE_LINKS][i];
                if (e.end == n) {
                    return e;
                }
            }
            return undefined;
        }
        typedNodes(type) {
            let nlk = [];
            this[Private.NODE_LINKS].forEach(e => {
                if (e.end?.type == type) {
                    nlk.push(e);
                }
            });
            return nlk;
        }
        next(extype = null) {
            let links = [];
            if (extype !== "consonant") {
                links.push(...this.typedNodes("consonant"));
            }
            if (extype !== "vowel") {
                links.push(...this.typedNodes("vowel"));
            }
            if (extype !== "other") {
                links.push(...this.typedNodes("other"));
            }
            let maxv = 0;
            links.forEach(l => {
                maxv += l.weight;
            });
            let rnd = Math.limitRandom(0, maxv);
            let cw = 0;
            let r = undefined;
            for (let i = 0; i < links.length; i++) {
                const e = links[i];
                if (cw > rnd) {
                    break;
                }
                cw += e?.weight ?? 0;
                r = e?.end;
            }
            return r;
        }
    }
    Project.Node = Node;
    class NodeLink {
        [Private.LINK_PRIVATE];
        constructor(owner, to, w) {
            resetPrototype(this);
            this[Private.LINK_PRIVATE] = {
                node: to,
                start: owner,
                weight: 0
            };
            owner[Private.NODE_LINKS].push(this);
            Object.defineProperty(this, "begin", {
                configurable: false,
                enumerable: true,
                get: () => {
                    return this[Private.LINK_PRIVATE].start;
                }
            });
            Object.defineProperty(this, "end", {
                configurable: false,
                enumerable: true,
                get: () => {
                    return this[Private.LINK_PRIVATE].node;
                }
            });
            this.weight = w;
        }
        remove() {
            if (!this[Private.LINK_PRIVATE].start) {
                return;
            }
            this[Private.LINK_PRIVATE].start[Private.NODE_LINKS].splice(this[Private.LINK_PRIVATE].start[Private.NODE_LINKS].indexOf(this), 1);
            this[Private.LINK_PRIVATE].start = null;
        }
        valid() {
            return !!this[Private.LINK_PRIVATE].start;
        }
        get weight() {
            return this[Private.LINK_PRIVATE].weight;
        }
        set weight(v) {
            this[Private.LINK_PRIVATE].weight = numberToUInt(v);
            if (isNaN(this[Private.LINK_PRIVATE].weight)) {
                this[Private.LINK_PRIVATE].weight = 0;
            }
        }
    }
    Project.NodeLink = NodeLink;
    Project.Letters = {
        selectors: new SDT.Registry(),
        chars: new SDT.Registry(undefined, (v, v2) => {
            return v.letter === v2.letter;
        }),
        root: new Project.Node('', "other"),
    };
    Object.setPrototypeOf(Project.Letters, null);
    const wva = {
        configurable: false,
        deletable: false,
        enumerable: true,
        readonly: true
    };
    Project.Letters.chars.write('root', Project.Letters.root, wva);
    Project.Letters.chars.write('А', new Project.Node('а', "vowel"), wva);
    Project.Letters.chars.write('Е', new Project.Node('е', "vowel"), wva);
    Project.Letters.chars.write('Ё', new Project.Node('ё', "vowel"), wva);
    Project.Letters.chars.write('И', new Project.Node('и', "vowel"), wva);
    Project.Letters.chars.write('О', new Project.Node('о', "vowel"), wva);
    Project.Letters.chars.write('У', new Project.Node('у', "vowel"), wva);
    Project.Letters.chars.write('Ы', new Project.Node('ы', "vowel"), wva);
    Project.Letters.chars.write('Э', new Project.Node('э', "vowel"), wva);
    Project.Letters.chars.write('Ю', new Project.Node('ю', "vowel"), wva);
    Project.Letters.chars.write('Я', new Project.Node('я', "vowel"), wva);
    Project.Letters.chars.write('А', new Project.Node('ъ', "other"), wva);
    Project.Letters.chars.write('А', new Project.Node('ь', "other"), wva);
    Project.Letters.chars.write('Б', new Project.Node('б', "consonant"), wva);
    Project.Letters.chars.write('В', new Project.Node('в', "consonant"), wva);
    Project.Letters.chars.write('Г', new Project.Node('г', "consonant"), wva);
    Project.Letters.chars.write('Д', new Project.Node('д', "consonant"), wva);
    Project.Letters.chars.write('Ж', new Project.Node('ж', "consonant"), wva);
    Project.Letters.chars.write('З', new Project.Node('з', "consonant"), wva);
    Project.Letters.chars.write('Й', new Project.Node('й', "consonant"), wva);
    Project.Letters.chars.write('К', new Project.Node('к', "consonant"), wva);
    Project.Letters.chars.write('Л', new Project.Node('л', "consonant"), wva);
    Project.Letters.chars.write('М', new Project.Node('м', "consonant"), wva);
    Project.Letters.chars.write('Н', new Project.Node('н', "consonant"), wva);
    Project.Letters.chars.write('П', new Project.Node('п', "consonant"), wva);
    Project.Letters.chars.write('Р', new Project.Node('р', "consonant"), wva);
    Project.Letters.chars.write('С', new Project.Node('с', "consonant"), wva);
    Project.Letters.chars.write('Т', new Project.Node('т', "consonant"), wva);
    Project.Letters.chars.write('Ф', new Project.Node('ф', "consonant"), wva);
    Project.Letters.chars.write('Х', new Project.Node('х', "consonant"), wva);
    Project.Letters.chars.write('Ц', new Project.Node('ц', "consonant"), wva);
    Project.Letters.chars.write('Ч', new Project.Node('ч', "consonant"), wva);
    Project.Letters.chars.write('Щ', new Project.Node('ш', "consonant"), wva);
    Project.Letters.chars.write('Ш', new Project.Node('щ', "consonant"), wva);
    Project.Letters.selectors.write("vowels", [
        'А', 'Е', 'Ё', 'И', 'О', 'У', 'Э', 'Ю', 'Я'
    ]);
    Project.Letters.selectors.write("static-vowels", [
        'А', 'Е', 'И', 'О', 'У', 'Э'
    ]);
    Project.Letters.selectors.write("consonants", [
        'Б', 'В', 'Г', 'Д', 'Ж', 'З', 'К', 'Л', 'М',
        'Н', 'П', 'Р', 'С', 'Т', 'Ф', 'Х'
    ]);
    Project.Letters.selectors.write("hissingoffensive", [
        'Ш', 'Щ', 'Ц', 'Ч'
    ]);
    function link(src, dest, weight = 1, double = false) {
        function __parse_path(path) {
            let r = [];
            if (path == '~' || path == 'root') {
                r = [Project.Letters.root];
            }
            else if (path[0] == '/') {
                let cn = Project.Letters.chars.read(path.substring(1));
                r = cn ? [cn] : [];
            }
            else if (path[0] == '@') {
                let cnl = Project.Letters.selectors.read(path.substring(1));
                cnl?.forEach(e => {
                    let cn = Project.Letters.chars.read(e);
                    if (cn) {
                        r.push(cn);
                    }
                });
            }
            return r;
        }
        const sarr = __parse_path(src);
        const darr = __parse_path(dest);
        function __link(s, d) {
            s.forEach(e => {
                d.forEach(et => {
                    if (e != et) {
                        e.link(et, weight);
                    }
                });
            });
        }
        __link(sarr, darr);
        if (double) {
            __link(darr, sarr);
        }
    }
    Project.link = link;
    function generate(startNode, wordLength, maxOneTypeRepeat) {
        let lastType = startNode.type;
        let lastTypeRepeat = 0;
        maxOneTypeRepeat = Math.max(numberToInt(maxOneTypeRepeat), 1);
        wordLength = numberToUInt(wordLength);
        let r = "";
        let cnode = startNode;
        for (let i = 0; i <= wordLength && cnode; i++) {
            if (lastType == cnode.type) {
                lastTypeRepeat++;
            }
            else {
                lastType = cnode.type;
                lastTypeRepeat = 0;
            }
            r += cnode.letter;
            cnode = cnode.next(lastTypeRepeat >= maxOneTypeRepeat ? lastType : null);
        }
        return r;
    }
    Project.generate = generate;
    const storageRequest = indexedDB.open("SooperADS::WordMeker@index", 1);
    Project.appStorage = undefined;
    storageRequest.onsuccess = function () {
        Project.appStorage = storageRequest.result;
        let t = Project.appStorage.transaction("words", "readonly");
        let s = t.objectStore("words");
        let rc = s.openCursor(undefined, "nextunique");
        rc.onerror = function () {
            console.error(rc.error);
        };
        rc.onsuccess = function () {
            const c = rc.result;
            if (c) {
                po.append(addWordToTable(new Word(c.value)));
                c.continue();
            }
        };
    };
    storageRequest.onerror = function () {
        console.error(storageRequest.error);
    };
    storageRequest.onupgradeneeded = function (e) {
        let db = storageRequest.result;
        switch (e.oldVersion) {
            case 0:
                db.createObjectStore('words', {
                    autoIncrement: false,
                    keyPath: "uuid"
                });
        }
    };
})(Project || (Project = {}));
Object.setPrototypeOf(Project, null);
Project.link("@consonants", "@vowels", 1, true);
Project.link("@consonants", "@hissingoffensive", 0.5, true);
Project.link("@hissingoffensive", "/А", 1);
Project.link("@hissingoffensive", "/Е", 1);
Project.link("@hissingoffensive", "/И", 1);
Project.link("@hissingoffensive", "/О", 1);
Project.link("@hissingoffensive", "/У", 1);
Project.link("@hissingoffensive", "/Э", 1);
Project.link("/А", "@hissingoffensive", 0.75);
Project.link("/Е", "@hissingoffensive", 0.75);
Project.link("/И", "@hissingoffensive", 0.75);
Project.link("/О", "@hissingoffensive", 0.75);
Project.link("/У", "@hissingoffensive", 0.75);
Project.link("/Э", "@hissingoffensive", 0.75);
Project.link("@consonants", "/Ь", 0.2);
Project.link("@consonants", "/Ы", 0.75);
Project.link("/Ы", "@consonants", 1);
Project.link("/Ы", "@hissingoffensive", 0.75);
Project.link("/Ь", "@static-vowels", 1);
Project.link("/Й", "@static-vowels", 1);
Project.link('root', "@consonants", 1);
Project.link('root', "@vowels", 1);
Project.link('root', "@hissingoffensive", 1);
Project.link('root', "/Й", 0.7);
function RandomWord(maxLength, maxOTR = 2) {
    return Project.generate(Project.Letters.root, Math.intRandom(2, Math.max(maxLength, 2)), maxOTR);
}
class Word {
    content;
    uuid;
    date;
    save;
    constructor(v) {
        Object.setPrototypeOf(Object.getPrototypeOf(this) ?? this, null);
        if (typeof v == "number") {
            this.content = RandomWord(v);
            this.uuid = crypto.randomUUID();
            this.date = new Date();
            this.save = false;
        }
        else {
            this.content = v.content;
            this.uuid = v.uuid;
            this.date = v.date;
            this.save = true;
        }
    }
    dbword() {
        return {
            uuid: this.uuid,
            content: this.content,
            date: this.date
        };
    }
}
function addWordToTable(w) {
    let r = document.createElement("tr");
    const uuid = document.createElement("td");
    uuid.innerHTML = `<code>${w.uuid}</code>`;
    const date = document.createElement("td");
    date.innerHTML = `${w.date.toLocaleDateString()} / ${w.date.toLocaleTimeString()}`;
    const word = document.createElement("td");
    word.innerHTML = `<code>${w.content}</code>`;
    const cbid = `i-cb/${w.uuid}`;
    const save = document.createElement("td");
    save.setAttribute("align", "center");
    save.innerHTML = `<input type="checkbox" id="${cbid}" /><label for="${cbid}"></label>`;
    const saveCB = save.getElementsByTagName("input")[0];
    if (w.save) {
        saveCB.checked = true;
    }
    saveCB.addEventListener("change", () => {
        let ts = Project.appStorage?.transaction("words", "readwrite").objectStore("words");
        if (ts) {
            if (saveCB.checked && !w.save) {
                ts.add(w.dbword());
                w.save = true;
            }
            else if (w.save) {
                ts.delete(w.uuid);
                w.save = false;
            }
        }
    });
    r.append(uuid, date, word, save);
    return r;
}
genb.addEventListener('click', () => {
    if (gcInput.validity.valid && glenInput.validity.valid) {
        for (let i = 0; i < +gcInput.value; i++) {
            po.append(addWordToTable(new Word(+glenInput.value)));
        }
    }
});
function randomWordTest(count, maxLength = 8) {
    console.group("Генерация", count, "случайных слов:");
    for (let i = 0; i < count; i++) {
        let w = RandomWord(maxLength, 2);
        const wo = new Word({
            content: w,
            date: new Date(),
            uuid: crypto.randomUUID()
        });
        wo.save = false;
        po.append(addWordToTable(wo));
        console.log(w);
    }
    console.groupEnd();
}
setTimeout(() => {
    randomWordTest(Math.intRandom(2, 7), 15);
}, 100);
//# sourceMappingURL=Client.js.map